
import sqlite3
from ns import Ns
from setting import logger, NS_HOST
import json
import websocket

class Sentry:


    def __init__(self) -> None:

        self.ns = Ns(NS_HOST)
        
        self.init_db() 

        self.event_insert_db() # 将事件插入db

    @staticmethod
    def dict_factory(cursor, row):
        d = {}
        for idx, col in enumerate(cursor.description):
            d[col[0]] = row[idx]
        return d  



    def init_db(self): # 初始化数据库

        conn = sqlite3.connect('data.sqlite3')
        cursor = conn.cursor()

        create_table_query = '''
        CREATE TABLE IF NOT EXISTS events (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            entity TEXT,
            eid TEXT,
            text TEXT,
            raw_json TEXT UNIQUE,
            status TEXT -- null 代表未处理 handle 代表已经处理
        );
        '''
        cursor.execute(create_table_query)

        conn.commit()
        conn.close()

    def event_insert_db(self): # 将报警事件插入events表中

        events = self.ns.get_event()

        conn = sqlite3.connect('data.sqlite3')

        cursor = conn.cursor()

        insert_data_query = '''
            INSERT INTO events (entity, eid, text, raw_json) 
            VALUES (?, ?, ?, ?)
        '''

   
        for i in events:

            logger.info(i)

            # 要插入的数据
            try:
                data = (i['entity'], i['eid'], i['text'], json.dumps(i))


            # 执行插入数据的操作
                cursor.execute(insert_data_query, data)

            except sqlite3.IntegrityError as e:

                if "UNIQUE constraint failed" in e.args[0] == False:

                    raise

            except KeyError as e:

                logger.error(e.args[0])

            else:

            # 提交更改并关闭连接
                conn.commit()

        cursor.close()
        conn.close()

    def reset_fcnt_value(self): # 有报fcnt_gap_too_large错误的清零

        conn = sqlite3.connect('data.sqlite3')
        conn.row_factory = self.dict_factory
        cursor = conn.cursor()


        sql = "select * from events where status is null and text='fcnt_gap_too_large'"

        cursor.execute(sql)

        res = cursor.fetchall()

        for i in res:

            self.ns.reset_fcnt(i["eid"])

            update_sql = "update events set status='handle' where id=?"

            cursor.execute(update_sql, (i["id"], ))

        conn.commit()

        cursor.close()

        conn.close()

    def add_sensor_downlink_massage(self): # dowlink为空的传感器添加标记downlinks

        nodes = self.ns.get_all_nodes()

        logger.info(f"nodes list: {nodes}")

        websocket.enableTrace(True)

        for i in nodes:

            print(i)

            downlinks = self.ns.get_downlinks(i["devaddr"])

            if downlinks == []:


                ws = f"ws://{NS_HOST}/ws/uplink/{i['devaddr']}"

                ws = websocket.create_connection(ws)

                msg = {"data": "363636", "port": 12}
                ws.send(json.dumps(msg))
                # result = ws.recv()  # 以阻塞方式接收响应
                # print("Received message:", result)
                ws.close()

                logger.info(f"{i['devaddr']} -- add downlinks message")

if __name__ == "__main__":

    import time

    while True:

        s = Sentry()

        s.reset_fcnt_value()
    
        s.add_sensor_downlink_massage()

        time.sleep(3)

    

